#include "Complex.h"
#include <stdio.h>
#include <math.h>
#include <bitset>


Complex&    Complex::operator=(const Complex& _other)
{
    if (this == &_other)
    {
        return *this; // handle self assignment
    }

    real = _other.real;
    imag = _other.imag;

    return *this;
}

Complex&     Complex::operator +=(const Complex& _other)
{
    real += _other.real;
    imag += _other.imag;

    return *this;
}

Complex     Complex::operator+ (const Complex& _other)
{
    Complex tmp(_other);

    tmp.operator+=(*this);

    return tmp;
}

Complex     Complex::operator- (const Complex& _other)
{
    Complex tmp(*this);

    tmp.operator-=(_other);

    return tmp;
}

Complex&     Complex::operator -=(const Complex& _other)
{
    real -= _other.real;
    imag -= _other.imag;

    return *this;
}

Complex&     Complex::operator *=(const Complex& _other)
{
    real=(real*_other.real)-(imag*_other.imag);
    imag=(real*_other.imag)+(imag*_other.real);

    return *this;
}

Complex Complex::operator *(const Complex& _other)
{
    Complex tmp(*this);

    tmp.operator*=(_other);

    return tmp;
}



Complex     Complex::operator /(const Complex& _other)
{
    float div = ( _other.real * _other.real ) + ( _other.imag * _other.imag );
    float Treal = ( (real*_other.real) + (imag*_other.imag) ) / div ;
    float Timag = ( (imag*_other.real) - (real*_other.imag) ) / div ;
    Complex tmp(Treal,Timag);

    return tmp;
}

Complex Complex::getconjugate()
{
    Complex tmp(this->real,this->imag * -1);

    return tmp;
}

Complex Complex::getreciprocal()
{
    float div = (real*real)+(imag*imag);

    Complex     tmp( real / div , (imag * -1) / div );

    return tmp;
}

float Complex::getmodulus()
{
    float z = (real*real)+(imag*imag);

    return sqrt(z);
}

void Complex::setdata(float _real,float  _imag)
{
    real = _real;
   imag  = _imag;
}


istream&      operator>> (istream& is,Complex& _this)
{
    cout<<"Enter Real:"<<endl;
    is >> _this.real;
    cout<<"Enter Imaginary:"<<endl;
    is >> _this.imag;
    return is;
}

bool Complex::operator == (const Complex& _other)
{
    return (real==_other.real)&&(imag==_other.imag) ? 1 : 0;
}

ostream& operator <<(ostream& os,const Complex& _this)
{
     os<<"Real Part = "<<_this.real<<endl
    <<"Imaginary Part = "<<_this.imag<<endl;
    os << "z = " << _this.real
    <<_this.imag<<"i"<<endl;

    if (_this.real>0 && _this.imag>0)
    {
        os<<"  degree-->"<<atan(_this.imag / _this.real)<<endl;
    }
    else if(_this.real > 0 && _this.imag<0 )
    {
        os<<"  degree-->"<<(atan(_this.imag / _this.real) + 360 )<<endl;
    }
    else if(_this.real < 0)
    {
        os<<"  degree-->"<<(atan(_this.imag / _this.real) + 180 )<<endl;
    }
    else if(!_this.real && _this.imag > 0 )
    {
        os<<"  degree-->"<<"90"<<endl;
    }
    else if(!_this.real && _this.imag < 0 )
    {
        os<<"  degree-->"<<"270"<<endl;
    }

    return os;
}



int main()
{
    Complex a(2.0f,-2.f),e; // Calls Constructor
    cout<<a<<endl;         // Calls the overloaded << operator
    Complex b(-2,-2);      // Calls Constructor
    Complex c=b;           // Calls Copy Constructor
    c=a;                   // calls overloaded = operator

    cin>>e;

    cout<<a<<" / "<<e<<" is "<<(a/e)<<endl;



    if(b == c)               // calls overloaded == operator
      cout<<"b == c";
      else
      cout<<"b != c";

    cout<<endl<<"modulo of"<<c.Getimag()<<" and "<<c.Getreal()<<" is "<<c.getmodulus()<<endl; // calls getmodulus function()

    Complex d;
    d=a+b;   // Calls overloaded +
    cout<<d<<endl;
    d=a-b;     // Calls overloaded -
    cout<<d<<endl;
    d=a*b;        // calls overloaded *
    cout<<d<<endl;
    d=a/b;        // calls overloaded /
    cout<<d<<endl;

    return 0;
}
